#ifndef ACUAS_H
#define ACUAS_H
/** @mainpage ACUAS mCEasy Version 2012
*
* @section sec1 Introduction

<img src="ACUAS-mCEasy.jpg" alt="ACUAS mC Board">

For beginners the programming of microcontrollers is hard. Even if they have already programming experience in programming PCs the handling of the microcontroller specific hardware can be a challenge.
Not only the 351 pages of the ATmega16 data sheet must be understood but a lot of experience in assembler programming is required. Even then it can be a tedious and frustrating work.
The goal of our approach is to provide a hardware and software environment for beginners  in the domain of microcontrollers who want to explore the potentials. In addition the flexible concept provides the full advantage of C for experienced microcontroller programmers.

The mCEasy programming interface provides a set of instructions which program the microcontroller on the ACUAS board. Programming and testing is done a PC. During build time the instructions are preprocessed to C programming language and then compiled and linked. The result is a .hex file which can be transferred the controller. For uploading the hex file to the microcontroller see appendix.

Technically the instructions are C macros by which the concept is fully integrated with C. Hence all C programming features can optionally be used and mixed with the mCEasy Programming instructions. This assures full flexibility as the student wants to program more sophisticated algorithms.

 @author Thomas Siepmann, Aachen University of Applied Sciences, Germany, 2012
 @see http://www.siepmann.fh-aachen.de
*/


/**
 @defgroup ACUAS_EP ACUAS Easy Programming

 @brief C macros to easily program the ACUAS ATmega16/ATmega32 board.
 @author Thomas Siepmann, Aachen University of Applied Sciences, Germany
 @see http://www.siepmann.fh-aachen.de
 */

/// @{
/// @file ACUAS.h
/// @file ACUAS.c

#ifdef BUTTERFLY
#include <ACUAS-Butterfly.h>

#endif

#ifndef F_CPU
/// default processor speed (used for WAIT_SEC and UART)
#define F_CPU 100000UL
#endif

#include <avr/io.h>
#include <stdlib.h>
#include <math.h>

void set_seed(void);
void InitBoard(void);
void delay_ds(unsigned char ds);
void autoADCps(void);
void Sound_Init(int t,float x);
void Volumen(int vol);

/**
 *  @name  Program main structure
 Set simulation modus:
 No waiting (WAIT_SEC) and constant random seed (for testing). Must be the first line in .c file:
 define \#SIMULATION
 */
/// Begin of instructions which are carried out only one time at the beginning of the program
#define PROGRAM_INIT   int main(void){InitBoard();
/// Begin of instructions which are carried out in an endless loop.
#define PROGRAM_START  while(1){
/// End of the program
#define PROGRAM_END	 } return 0;}

/**
 *  @name  Define Variables
 */
/// Declares a 32 bit integer variable with a range from - 2147483648 to + 2147483648
#define VARIABLE(v) signed long int v;
/// Declares a 16 bit unsigned variable with a range from 0 to 65535
#define VAR16(v) uint16_t v;
/// Declares a 8 bit unsigned variable with a range from 0 to 255
#define VAR(v) unsigned char v;
/// Declares a character array s which can contain a string of max characters
#define STRING(s,max) unsigned char s[(max)+1];
/// Declares a CONSTANT character array s which contains the string string
#define STRING_CONST(s,string) static const char s[] PROGMEM = string;
/// Begin of instructions which are carried out only one time at the beginning of the program
#define PROGRAM_INIT   int main(void){InitBoard();
/// Begin of instructions which are carried out in an endless loop.
#define PROGRAM_START  while(1){
/// End of the program
#define PROGRAM_END	 } return 0;}

/**
 *  @name  Define Variables
 */
/// Declares a 32 bit integer variable with a range from - 2147483648 to + 2147483648
#define VARIABLE(v) signed long int v;
/// Declares a 16 bit unsigned variable with a range from 0 to 65535
#define VAR16(v) uint16_t v;
/// Declares a 8 bit unsigned variable with a range from 0 to 255
#define VAR(v) unsigned char v;
/// Declares a character array s which can contain a string of max characters
#define STRING(s,max) unsigned char s[(max)+1];
/// Declares a CONSTANT character array s which contains the string string
#define STRING_CONST(s,string) static const char s[] PROGMEM = string;

/**
 *  @name  Miscellaneous
 */
/// Empty instruction. Continues immediately with the next instruction. Can be used for empty loops or before else conditions. Consumes no time.
#define DO_NOTHING ;
/// Waits x seconds. Range of x i from 0.1 to 25
#define WAIT_SEC(x) delay_ds(x*10);
/// Sets the bit number b to 1. Ex.: SET_BIT(PORTC, 7)
#define SET_BIT(r,b) (r) |= 1 << (b);
/// Sets the bit number b to 0. Ex.: CLEAR_BIT(PORTC, 7)
#define CLEAR_BIT(r,b) (r) &= ~(1 << (b));
/// Initialize the random generator. Must be invoked in the PROGRAM_INIT part. The seed is derived from the SRAM initial values at startup time.
#define RANDOM_INIT set_seed();
/**
 *  @brief   Generates a random integer number
 *  @param   n Minimal random integer value
 *  @param   m Maximal random integer value
 *  @return  random number between n and m (including)
 */
#define RANDOM(n,m)(n + random()%(m-n+1))

/**
 *  @name  LEDs
 *  LED numbering is 1 based
 */


/**
 *  @name  Buttons and joystick

 */
/**
 *  @name  Joystick up
 */
///Execute the following instruction if the joystick up button is pressed
#define ON_JOYSTICK_UP     if(!(PINB & (1 << 6)))
///Execute the following instruction if the joystick up button is not pressed
#define OFF_JOYSTICK_UP      if(PINB & (1 << 6))
///Wait until the joystick up button is pressed
#define WAIT_FOR_JOYSTICK_UP while(PINB & (1 << 6));
///Wait until the joystick up button is released
#define WAIT_FOR_RELEASE_JOYSTICK_UP while(!(PINB & (1 << 6)));
/**
 *  @name  Joystick down
 */
///Execute the following instruction if the joystick down button is pressed
#define ON_JOYSTICK_DOWN   if(!(PINB & (1 << 7)))
///Execute the following instruction if the joystick down button is not pressed
#define OFF_JOYSTICK_DOWN    if(PINB & (1 << 7))
///Wait until the joystick down button is pressed
#define WAIT_FOR_JOYSTICK_DOWN while(PINB & (1 << 7));
///Wait until the joystick down button is released
#define WAIT_FOR_RELEASE_JOYSTICK_DOWN while(!(PINB & (1 << 7)));
/**
 *  @name  Joystick right
 */
///Execute the following instruction if the joystick right button is pressed
#define ON_JOYSTICK_RIGHT  if(!(PINE & (1 << 3)))
///Execute the following instruction if the joystick right button is not pressed
#define OFF_JOYSTICK_RIGHT   if(PINE & (1 << 3))
///Wait until the joystick right button is pressed
#define WAIT_FOR_JOYSTICK_RIGHT while(PINE & (1 << 3));
///Wait until the joystick right button is released
#define WAIT_FOR_RELEASE_JOYSTICK_RIGHT while(!(PINE & (1 << 3)));
/**
 *  @name  Joystick left
 */
///Execute the following instruction if the joystick left button is pressed
#define ON_JOYSTICK_LEFT   if(!(PINE & (1 << 2)))
///Execute the following instruction if the joystick left button is not pressed
#define OFF_JOYSTICK_LEFT    if(PINE & (1 << 2))
///Wait until the joystick left button is pressed
#define WAIT_FOR_JOYSTICK_LEFT while(PINE & (1 << 2));
///Wait until the joystick left button is released
#define WAIT_FOR_RELEASE_JOYSTICK_LEFT while(!(PINE & (1 << 2)));
/**
*  @name  Joystick center
 */
///Execute the following instruction if the joystick left button is pressed
#define ON_JOYSTICK_CENTER   if(!(PINB & (1 << 4)))
///Execute the following instruction if the joystick left button is not pressed
#define OFF_JOYSTICK_CENTER    if(PINB & (1 << 4))
///Wait until the joystick left button is pressed
#define WAIT_FOR_JOYSTICK_CENTER while(PINB & (1 << 4));
///Wait until the joystick left button is released
#define WAIT_FOR_RELEASE_JOYSTICK_CENTER while(!(PINB & (1 << 4)));
/**

 *  @name  AD converter
 *  Channel numbering is 1 based!
 */
  /// Activate ADC with Prescaler 16 --> 1Mhz/16 = 62.5kHz. ADEN=AD enable, ADPSx automatic preselection. Reference voltage = AVCC
#define ACTIVATE_ADC  {ADCSRA = (1<<ADEN); ADMUX |= (0<<REFS1) | (1<<REFS0); autoADCps();}
  /// Select channel. Channel numbering is 1 based
#define ADC_CHANNEL(ch) ADMUX &= 0b11110000; ADMUX |= (ch-1); if(ch<=3){ PORTF &= ~(1 << (ch-1));}
  /// Start one 10 bit AD conversion. Wait until conversion completed
#define START_ADC {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);}
/// Perform a 10 bit AD conversion and store the value in a 8 bit variable
#define ADCONVERTlow(vc) {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);vc=ADCW >> 2;}
/// Perform  a 10 bit AD conversion and store the digital value in a 16 bit variable
#define ADCONVERT(x) {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);x=ADCW;}
/// Perform  a 10 bit AD conversion and store the result in mV in an integer (or double or float) variable
#define ADCONVERT_MV(x) {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);x=ADCW*5./1.024;}
/// Perform  a 10 bit AD conversion and store the result in mV in an integer (or double or float) variable
#define BRIGHTNESS(x) ACTIVATE_ADC ADC_CHANNEL(1) {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);x=ADCW*5./1.024;}
/// Perform  a 10 bit AD conversion and store the result in mV in an integer (or double or float) variable
#define VOLTAGE(x) ACTIVATE_ADC ADC_CHANNEL(2) {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);x=ADCW*5/1023;}
/// Perform  a 10 bit AD conversion and store the result in mV in an integer (or double or float) variable
#define TEMPERATURE(x) ACTIVATE_ADC ADC_CHANNEL(3) {ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);ADCSRA |= (1<<ADSC); loop_until_bit_is_clear(ADCSRA,ADSC);x=((4250/(log(ADCW/(1024-ADCW))+(4250/298)))-273);}
// FUNCTIONS
// #include "ACUAS.c"
/**
 *  @name  LCD Output
 */
char lcd_str[21];
int j;
/// Clear LCD screen
#define CLEAR_LCD {LCD_Clear(),j=0;}
/// Initializes the LCD and clears the screen
#define START_LCD {LCD_Init ();sei();}
/// Write string at cursor position
#define LCD_TEXT(string)  {for (j; j<1;j++){LCD_puts(string,1);LCD_Colon(0);}}
/// Write character at cursor position
/// Write string at cursor position
#define LCD_NUMBER(v) {itoa(v,lcd_str,10); LCD_puts(lcd_str,1);};
/// Write character at cursor position
#define LCD_CHAR(n)  LCD_putc(n);
/// Write integer number at cursor position
#define LCD_D_NUMBER(v,w,p) {for (j; j<1;j++){dtostrf(v,w,p,lcd_str); LCD_puts(lcd_str,1);LCD_Colon(0);}}
// FUNCTIONS
// #include "sound.c"
/**
 *  @name  BEEP Output
 */
/// Defines the speaker volume 
#define BEEP_VOLUME(vol) Volumen(vol);

/// Frequency and operation time of the speaker 
#define BEEP(f,t) { Sound_Init(f,t);}
/*@}*/
#endif // ACUAS_H
